﻿using System;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Data;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using System.Reflection;
using System.Collections;
using System.Globalization;
using System.ComponentModel;
using System.Security;
using System.Security.Cryptography;
using System.Runtime;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;

using Microsoft.SqlServer.Server;

namespace PickGold.SqlServer
{
	/// <summary>
	/// 位操作支持
	/// </summary>
	public static class Bit
	{
		/// <summary>
		/// 位或
		/// </summary>
		/// <param name="left">左操作数</param>
		/// <param name="right">右操作数</param>
		/// <returns>位或结果</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary BitOr(SqlBinary left, SqlBinary right)
		{
			int i;
			if (left.IsNull || left.Value == null || left.Length == 0)
			{
				if (right.IsNull || right.Value == null)
					return new SqlBinary();

				return right;
			}

			if (right.IsNull || right.Value == null || right.Length == 0)
				return left;

			byte[] bs;
			if (left.Length > right.Length)
				bs = new byte[left.Length];
			else
				bs = new byte[right.Length];
			for (i = 0; i < left.Length && i < right.Length; i++)
				bs[i] = (byte)(left[i] | right[i]);
			if (left.Length == right.Length)
				return new SqlBinary(bs);

			if (left.Length > right.Length)
			{
				for (i = bs.Length; i < left.Length; i++)
					bs[i] = left[i];
			}
			else
			{
				for (i = bs.Length; i < left.Length; i++)
					bs[i] = right[i];
			}
			return new SqlBinary(bs);
		}

		/// <summary>
		/// 位与
		/// </summary>
		/// <param name="left">左操作数</param>
		/// <param name="right">右操作数</param>
		/// <returns>位与结果</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary BitAnd(SqlBinary left, SqlBinary right)
		{
			int i;
			if (left.IsNull || left.Value == null || left.Length == 0 || right.IsNull || right.Value == null || right.Length == 0)
				return new SqlBinary();

			byte[] bs;
			if (left.Length > right.Length)
				bs = new byte[right.Length];
			else
				bs = new byte[left.Length];
			for (i = 0; i < left.Length && i < right.Length; i++)
				bs[i] = (byte)(left[i] & right[i]);
			return new SqlBinary(bs);
		}

		/// <summary>
		/// 位异或
		/// </summary>
		/// <param name="left">左操作数</param>
		/// <param name="right">右操作数</param>
		/// <returns>位异或结果</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary BitXor(SqlBinary left, SqlBinary right)
		{
			int i;
			if (left.IsNull || left.Value == null || left.Length == 0)
			{
				if (right.IsNull || right.Value == null)
					return new SqlBinary();

				for (i = 0; i < right.Length; i++)
					right.Value[i] = (byte)(~right[i]);
				return right;
			}

			if (right.IsNull || right.Value == null || right.Length == 0)
			{
				for (i = 0; i < left.Length; i++)
					left.Value[i] = (byte)(~left[i]);
				return left;
			}

			byte[] bs;
			if (left.Length > right.Length)
				bs = new byte[left.Length];
			else
				bs = new byte[right.Length];
			for (i = 0; i < left.Length && i < right.Length; i++)
				bs[i] = (byte)(left[i] ^ right[i]);
			if (left.Length == right.Length)
				return new SqlBinary(bs);

			if (left.Length > right.Length)
			{
				for (i = bs.Length; i < left.Length; i++)
					bs[i] = (byte)(~left[i]);
			}
			else
			{
				for (i = bs.Length; i < left.Length; i++)
					bs[i] = (byte)(~right[i]);
			}
			return new SqlBinary(bs);
		}

		/// <summary>
		/// 位反
		/// </summary>
		/// <param name="data">操作数</param>
		/// <returns>位反结果</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary BitNot(SqlBinary data)
		{
			if (data.IsNull || data.Value == null || data.Length == 0)
				return new SqlBinary();

			for (int i = 0; i < data.Length; i++)
				data.Value[i] = (byte)(~data[i]);
			return data;
		}

		/// <summary>
		/// SubBinary
		/// </summary>
		/// <param name="data">SqlBinary</param>
		/// <param name="index">SqlInt32</param>
		/// <param name="length">SqlInt32</param>
		/// <returns>SqlBinary</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary SubBinary(SqlBinary data, SqlInt32 index, SqlInt32 length)
		{
			if (data.IsNull || data.Value == null || data.Length == 0)
				return new SqlBinary();

			if (length.IsNull || length.Value == 0)
				return null;

			if (index.IsNull)
				index = new SqlInt32(0);

			var ms = new MemoryStream();
			ms.Write(data.Value, index.Value, length.Value);
			var bs = ms.ToArray();
			ms.Close();
			ms.Dispose();
			return new SqlBinary(bs);
		}

		/// <summary>
		/// SubBinary
		/// </summary>
		/// <param name="data">SqlBinary</param>
		/// <param name="index">SqlInt32</param>
		/// <param name="length">SqlInt32</param>
		/// <returns>SqlBinary</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary ReverseBinary(SqlBinary data, SqlInt32 index, SqlInt32 length)
		{
			if (data.IsNull)
				return data;

			var bs = data.Value;
			if (bs == null || bs.Length == 0)
				return data;

			var l = bs.Length;
			var i = index.IsNull ? 0 : index.Value;
			if (i < 0)
				i += l;
			if (i >= l)
				i = l - 1;
			if (!length.IsNull)
				l = length.Value;
			if (l + i > bs.Length)
				l = bs.Length - i;
			Array.Reverse(bs, i, l);
			return new SqlBinary(bs);
		}

		#region BitConvert

		/// <summary/>
		[SqlFunction(IsDeterministic = true)]
		public static SqlInt64 DoubleToInt64Bits(SqlDouble data)
		{
			if(data.IsNull)
				return SqlInt64.Null;

			return BitConverter.DoubleToInt64Bits(data.Value);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true)]
		public static SqlDouble Int64BitsToDouble(SqlInt64 data)
		{
			if(data.IsNull)
				return SqlDouble.Null;

			return BitConverter.Int64BitsToDouble(data.Value);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBoolean ToBoolean(SqlBinary data, SqlInt32 index)
		{
			if(data.IsNull)
				return SqlBoolean.Null;

			var i = index.IsNull ? 0 : index.Value;
			if(i >= data.Length)
				return SqlBoolean.Null;

			return BitConverter.ToBoolean(data.Value, i);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlByte ToByte(SqlBinary data, SqlInt32 index)
		{
			if(data.IsNull)
				return SqlByte.Null;

			var i = index.IsNull ? 0 : index.Value;
			if(i >= data.Length)
				return SqlByte.Null;

			return data.Value[i];
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt16 ToInt16(SqlBinary data, SqlInt32 index)
		{
			if(data.IsNull)
				return SqlInt16.Null;

			var i = index.IsNull ? 0 : index.Value;
			if(i >= data.Length)
				return SqlInt16.Null;

			return BitConverter.ToInt16(data.Value, i);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt32 ToInt32(SqlBinary data, SqlInt32 index)
		{
			if(data.IsNull)
				return SqlInt32.Null;

			var i = index.IsNull ? 0 : index.Value;
			if(i >= data.Length)
				return SqlInt32.Null;

			return BitConverter.ToInt32(data.Value, i);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlInt64 ToInt64(SqlBinary data, SqlInt32 index)
		{
			if(data.IsNull)
				return SqlInt64.Null;

			var i = index.IsNull ? 0 : index.Value;
			if(i >= data.Length)
				return SqlInt64.Null;

			return BitConverter.ToInt64(data.Value, i);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true)]
		public static SqlSingle ToSingle(SqlBinary data, SqlInt32 index)
		{
			if(data.IsNull)
				return SqlSingle.Null;

			var i = index.IsNull ? 0 : index.Value;
			if(i >= data.Length)
				return SqlSingle.Null;

			return BitConverter.ToSingle(data.Value, i);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true)]
		public static SqlDouble ToDouble(SqlBinary data, SqlInt32 index)
		{
			if(data.IsNull)
				return SqlDouble.Null;

			var i = index.IsNull ? 0 : index.Value;
			if(i >= data.Length)
				return SqlDouble.Null;

			return BitConverter.ToDouble(data.Value, i);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary BooleanToBinary(SqlBoolean data)
		{
			if (data.IsNull)
				return SqlBinary.Null;

			return BitConverter.GetBytes(data.Value);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary ByteToBinary(SqlByte data)
		{
			if (data.IsNull)
				return SqlBinary.Null;

			return new byte[] { data.Value };
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary Int16ToBinary(SqlInt16 data)
		{
			if (data.IsNull)
				return SqlBinary.Null;

			return BitConverter.GetBytes(data.Value);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary Int32ToBinary(SqlInt32 data)
		{
			if (data.IsNull)
				return SqlBinary.Null;

			return BitConverter.GetBytes(data.Value);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary Int64ToBinary(SqlInt64 data)
		{
			if (data.IsNull)
				return SqlBinary.Null;

			return BitConverter.GetBytes(data.Value);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true)]
		public static SqlBinary SingleToBinary(SqlSingle data)
		{
			if (data.IsNull)
				return SqlBinary.Null;

			return BitConverter.GetBytes(data.Value);
		}

		/// <summary/>
		[SqlFunction(IsDeterministic = true)]
		public static SqlBinary DoubleToBinary(SqlDouble data)
		{
			if (data.IsNull)
				return SqlBinary.Null;

			return BitConverter.GetBytes(data.Value);
		}

		#endregion

		/// <summary>
		/// "67452301-AB89-EFCD-FEDC-BA9876543210"
		/// </summary>
		/// <param name="guid">SqlGuid</param>
		/// <returns>SqlBinary</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary GuidToBinary(SqlGuid guid)
		{
			if (guid.IsNull)
				return SqlBinary.Null;

			//System.Net.IPAddress.NetworkToHostOrder(0);
			//System.Net.IPAddress.HostToNetworkOrder(0);
			//BitConverter.ToString(BitConverter.GetBytes(0));
			//BitConverter.IsLittleEndian
			return new SqlBinary(guid.ToByteArray());
		}

		/// <summary>
		/// Zip
		/// </summary>
		/// <param name="data">SqlBinary</param>
		/// <param name="compress">SqlBoolean</param>
		/// <returns>SqlBinary</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary Zip(SqlBinary data, SqlBoolean compress)
		{
			var r = new MemoryStream();
			if (compress.IsNull || compress.IsFalse)
			{
				var ms = new MemoryStream(data.Value);
				var zip = new GZipStream(ms, CompressionMode.Decompress, true);
				var bs = data.Value;
				while (true)
				{
					var i = zip.Read(bs, 0, bs.Length);
					if (i == 0)
						break;

					r.Write(bs, 0, i);
				}
				ms.Close();
				ms.Dispose();
				zip.Close();
				zip.Dispose();
				data = new SqlBinary(r.ToArray());
			}
			else
			{
				var zip = new GZipStream(r, CompressionMode.Compress, true);
				zip.Write(data.Value, 0, data.Value.Length);
				zip.Close();
				zip.Dispose();
				data = new SqlBinary(r.ToArray());
			}
			r.Close();
			r.Dispose();
			return data;
		}

		/// <summary>
		/// 将指定的 System.String（它将二进制数据编码为 base 64 数字）转换成等效的 8 位无符号整数数组。
		/// </summary>
		/// <param name="value">输入字符串</param>
		/// <returns>等效于 s 的 8 位无符号整数数组。</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary GetBase64Binary(SqlString value)
		{
			if (value.IsNull || string.IsNullOrEmpty(value.Value))
				return null;

			return new SqlBinary(Convert.FromBase64String(value.Value));
		}

		/// <summary>
		/// 将 8 位无符号整数数组转换为它的等效 System.String 表示形式（使用 Base 64 数字编码）。
		/// </summary>
		/// <param name="value">输入字节流</param>
		/// <returns>value 内容的字符串表示形式，以基数为 64 的数字表示。</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlString GetBase64String(SqlBinary value)
		{
			if (value.IsNull || value.Value == null || value.Length == 0)
				return null;

			return new SqlString(Convert.ToBase64String(value.Value));
		}

		/// <summary>
		/// 将指定的 System.String（它将二进制数据编码为 base 32 数字）转换成等效的 8 位无符号整数数组。
		/// </summary>
		/// <param name="value">输入字符串</param>
		/// <returns>等效于 s 的 8 位无符号整数数组。</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlBinary GetBase32Binary(SqlString value)
		{
			if (value.IsNull)
				return SqlBinary.Null;

			var t = value.Value;
			if (value.IsNull || string.IsNullOrEmpty(value.Value))
				return SqlBinary.Null;

			const string T = "00112233445566778899AaBbCcDdEeFf";
			var bs = new byte[t.Length / 2];
			for (var i = 0; i < bs.Length; i++)
				bs[i] = (byte)((T.IndexOf(t[i * 2]) / 2 << 4) + T.IndexOf(t[i * 2 + 1]) / 2);
			return new SqlBinary(bs);
		}

		/// <summary>
		/// 将 8 位无符号整数数组转换为它的等效 System.String 表示形式（使用 Base 64 数字编码）。
		/// </summary>
		/// <param name="value">输入字节流</param>
		/// <returns>value 内容的字符串表示形式，以基数为 64 的数字表示。</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false)]
		public static SqlString GetBase32String(SqlBinary value)
		{
			if (value.IsNull)
				return SqlString.Null;

			var bs = value.Value;
			if (bs == null || bs.Length == 0)
				return SqlString.Null;

			const string T = "0123456789ABCDEF";
			var cs = new char[bs.Length * 2];
			for (var i = 0; i < bs.Length; i++)
			{
				cs[i * 2] = T[bs[i] >> 4];
				cs[i * 2 + 1] = T[bs[i] % 0x10];
			}
			return new SqlString(new string(cs));
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		/// <param name="length"></param>
		/// <returns></returns>
		[SqlFunction(IsDeterministic = true,
			IsPrecise = false,
			FillRowMethodName = "FillBlockSplit",
			TableDefinition = @"
[a] [varbinary](MAX),
[b] [varbinary](MAX),
[c] [varbinary](MAX),
[d] [varbinary](MAX),
[e] [varbinary](MAX),
[f] [varbinary](MAX),
[g] [varbinary](MAX),
[h] [varbinary](MAX),
[i] [varbinary](MAX),
[j] [varbinary](MAX),
[k] [varbinary](MAX),
[l] [varbinary](MAX),
[m] [varbinary](MAX),
[n] [varbinary](MAX),
[o] [varbinary](MAX),
[p] [varbinary](MAX),
[q] [varbinary](MAX),
[r] [varbinary](MAX),
[s] [varbinary](MAX),
[t] [varbinary](MAX),
[u] [varbinary](MAX),
[v] [varbinary](MAX),
[w] [varbinary](MAX),
[x] [varbinary](MAX),
[y] [varbinary](MAX),
[z] [varbinary](MAX)")]
		[Description("分割二进制串")]
		public static IEnumerable BlockSplit([Description("要分割二进制串")]SqlBinary data, [Description("每记录有元素（列/属性）多少个，最多不应超过26个")]SqlInt32 length)
		{
			if (data.IsNull || length.IsNull)
				yield break;

			var l = length.Value;
			if (l <= 0)
				yield break;

			var bs = data.Value;
			if (bs == null)
				yield break;

			var bl = bs.Length;
			if (bs.Length == 0)
				yield break;

			var rs = new SqlBinary[l];
			using (var ms = new MemoryStream(bs))
			{
				var ds = bs;
				bs = new byte[sizeof(int)];
				for (; ; )
				{
					for (var i = 0; i < l; i++)
					{
						bl -= sizeof(int);
						if (ms.Read(bs, 0, sizeof(int)) != sizeof(int))
						{
							if (i > 0)
							{
								for (; i < l; i++)
									rs[i] = SqlBinary.Null;
								yield return rs;
							}
							yield break;
						}

						var ii = BitConverter.ToInt32(bs, 0);
						if (ii <= 0)
						{
							if (i == 0)
								yield break;

							rs[i] = SqlBinary.Null;
							continue;
						}

						bl -= ii;
						if (bl < 0)//如果剩余为负数，表示数据不足
						{
							ii += bl;
							if (ii <= 0)
							{
								if (i == 0)
									yield break;

								rs[i] = SqlBinary.Null;
								continue;
							}
						}

						ds = new byte[ii];
						if (ms.Read(ds, 0, ii) != ii)
						{
							if (i > 0)
							{
								for (; i < l; i++)
									rs[i] = SqlBinary.Null;
								yield return rs;
							}
							yield break;
						}

						rs[i] = ds;
					}
					yield return rs;
				}
			}//using ms
		}

		private static void FillBlockSplit(object item,
			out SqlBinary a,
			out SqlBinary b,
			out SqlBinary c,
			out SqlBinary d,
			out SqlBinary e,
			out SqlBinary f,
			out SqlBinary g,
			out SqlBinary h,
			out SqlBinary i,
			out SqlBinary j,
			out SqlBinary k,
			out SqlBinary l,
			out SqlBinary m,
			out SqlBinary n,
			out SqlBinary o,
			out SqlBinary p,
			out SqlBinary q,
			out SqlBinary r,
			out SqlBinary s,
			out SqlBinary t,
			out SqlBinary u,
			out SqlBinary v,
			out SqlBinary w,
			out SqlBinary x,
			out SqlBinary y,
			out SqlBinary z)
		{
			const int aa = 0x00;
			const int bb = 0x01;
			const int cc = 0x02;
			const int dd = 0x03;
			const int ee = 0x04;
			const int ff = 0x05;
			const int gg = 0x06;
			const int hh = 0x07;
			const int ii = 0x08;
			const int jj = 0x09;
			const int kk = 0x0A;
			const int ll = 0x0B;
			const int mm = 0x0C;
			const int nn = 0x0D;
			const int oo = 0x0E;
			const int pp = 0x0F;
			const int qq = 0x10;
			const int rr = 0x11;
			const int ss = 0x12;
			const int tt = 0x13;
			const int uu = 0x14;
			const int vv = 0x15;
			const int ww = 0x16;
			const int xx = 0x17;
			const int yy = 0x18;
			const int zz = 0x19;

			if (item == null)
			{
				#region null

				a = SqlBinary.Null;
				b = SqlBinary.Null;
				c = SqlBinary.Null;
				d = SqlBinary.Null;
				e = SqlBinary.Null;
				f = SqlBinary.Null;
				g = SqlBinary.Null;
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			var bs = item as SqlBinary[];
			if (bs == null || bs.Length == aa)
			{
				#region aa

				a = SqlBinary.Null;
				b = SqlBinary.Null;
				c = SqlBinary.Null;
				d = SqlBinary.Null;
				e = SqlBinary.Null;
				f = SqlBinary.Null;
				g = SqlBinary.Null;
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			var bl = bs.Length;

			if (bl == bb)
			{
				#region bb

				a = (SqlBinary)bs[aa];
				b = SqlBinary.Null;
				c = SqlBinary.Null;
				d = SqlBinary.Null;
				e = SqlBinary.Null;
				f = SqlBinary.Null;
				g = SqlBinary.Null;
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == cc)
			{
				#region cc

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = SqlBinary.Null;
				d = SqlBinary.Null;
				e = SqlBinary.Null;
				f = SqlBinary.Null;
				g = SqlBinary.Null;
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == dd)
			{
				#region dd

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = SqlBinary.Null;
				e = SqlBinary.Null;
				f = SqlBinary.Null;
				g = SqlBinary.Null;
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == ee)
			{
				#region ee

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = SqlBinary.Null;
				f = SqlBinary.Null;
				g = SqlBinary.Null;
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == ff)
			{
				#region ff

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = SqlBinary.Null;
				g = SqlBinary.Null;
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == gg)
			{
				#region gg

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = SqlBinary.Null;
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == hh)
			{
				#region hh

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = SqlBinary.Null;
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == ii)
			{
				#region ii

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = SqlBinary.Null;
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == jj)
			{
				#region jj

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = SqlBinary.Null;
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == kk)
			{
				#region kk

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = SqlBinary.Null;
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == ll)
			{
				#region ll

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = SqlBinary.Null;
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == mm)
			{
				#region mm

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = SqlBinary.Null;
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == nn)
			{
				#region nn

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = SqlBinary.Null;
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == oo)
			{
				#region oo

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = SqlBinary.Null;
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == pp)
			{
				#region pp

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = SqlBinary.Null;
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == qq)
			{
				#region qq

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = SqlBinary.Null;
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == rr)
			{
				#region rr

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = SqlBinary.Null;
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == ss)
			{
				#region ss

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = (SqlBinary)bs[rr];
				s = SqlBinary.Null;
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == tt)
			{
				#region tt

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = (SqlBinary)bs[rr];
				s = (SqlBinary)bs[ss];
				t = SqlBinary.Null;
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == uu)
			{
				#region uu

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = (SqlBinary)bs[rr];
				s = (SqlBinary)bs[ss];
				t = (SqlBinary)bs[tt];
				u = SqlBinary.Null;
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == vv)
			{
				#region vv

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = (SqlBinary)bs[rr];
				s = (SqlBinary)bs[ss];
				t = (SqlBinary)bs[tt];
				u = (SqlBinary)bs[uu];
				v = SqlBinary.Null;
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == ww)
			{
				#region ww

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = (SqlBinary)bs[rr];
				s = (SqlBinary)bs[ss];
				t = (SqlBinary)bs[tt];
				u = (SqlBinary)bs[uu];
				v = (SqlBinary)bs[vv];
				w = SqlBinary.Null;
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == xx)
			{
				#region xx

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = (SqlBinary)bs[rr];
				s = (SqlBinary)bs[ss];
				t = (SqlBinary)bs[tt];
				u = (SqlBinary)bs[uu];
				v = (SqlBinary)bs[vv];
				w = (SqlBinary)bs[ww];
				x = SqlBinary.Null;
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == yy)
			{
				#region yy

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = (SqlBinary)bs[rr];
				s = (SqlBinary)bs[ss];
				t = (SqlBinary)bs[tt];
				u = (SqlBinary)bs[uu];
				v = (SqlBinary)bs[vv];
				w = (SqlBinary)bs[ww];
				x = (SqlBinary)bs[xx];
				y = SqlBinary.Null;
				z = SqlBinary.Null;

				#endregion

				return;
			}

			if (bl == zz)
			{
				#region zz

				a = (SqlBinary)bs[aa];
				b = (SqlBinary)bs[bb];
				c = (SqlBinary)bs[cc];
				d = (SqlBinary)bs[dd];
				e = (SqlBinary)bs[ee];
				f = (SqlBinary)bs[ff];
				g = (SqlBinary)bs[gg];
				h = (SqlBinary)bs[hh];
				i = (SqlBinary)bs[ii];
				j = (SqlBinary)bs[jj];
				k = (SqlBinary)bs[kk];
				l = (SqlBinary)bs[ll];
				m = (SqlBinary)bs[mm];
				n = (SqlBinary)bs[nn];
				o = (SqlBinary)bs[oo];
				p = (SqlBinary)bs[pp];
				q = (SqlBinary)bs[qq];
				r = (SqlBinary)bs[rr];
				s = (SqlBinary)bs[ss];
				t = (SqlBinary)bs[tt];
				u = (SqlBinary)bs[uu];
				v = (SqlBinary)bs[vv];
				w = (SqlBinary)bs[ww];
				x = (SqlBinary)bs[xx];
				y = (SqlBinary)bs[yy];
				z = SqlBinary.Null;

				#endregion

				return;
			}

			#region all

			a = (SqlBinary)bs[aa];
			b = (SqlBinary)bs[bb];
			c = (SqlBinary)bs[cc];
			d = (SqlBinary)bs[dd];
			e = (SqlBinary)bs[ee];
			f = (SqlBinary)bs[ff];
			g = (SqlBinary)bs[gg];
			h = (SqlBinary)bs[hh];
			i = (SqlBinary)bs[ii];
			j = (SqlBinary)bs[jj];
			k = (SqlBinary)bs[kk];
			l = (SqlBinary)bs[ll];
			m = (SqlBinary)bs[mm];
			n = (SqlBinary)bs[nn];
			o = (SqlBinary)bs[oo];
			p = (SqlBinary)bs[pp];
			q = (SqlBinary)bs[qq];
			r = (SqlBinary)bs[rr];
			s = (SqlBinary)bs[ss];
			t = (SqlBinary)bs[tt];
			u = (SqlBinary)bs[uu];
			v = (SqlBinary)bs[vv];
			w = (SqlBinary)bs[ww];
			x = (SqlBinary)bs[xx];
			y = (SqlBinary)bs[yy];
			z = (SqlBinary)bs[zz];

			#endregion
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		/// <param name="length"></param>
		/// <returns></returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false, FillRowMethodName = "FillRowSplit", TableDefinition = "[result] [varbinary](MAX)")]
		[Description("分割二进制串")]
		public static IEnumerable BinarySplit([Description("要分割二进制串")]SqlBinary data, [Description("定长分割，如果为空则表示每个元素前都带一个整数长度的前缀")]SqlInt32 length)
		{
			if (data.IsNull)
				yield break;

			var bs = data.Value;
			if (bs == null || bs.Length == 0 || length.IsNull)
			{
				yield return data;
				yield break;
			}

			var l = length.Value;
			if (l <= 0)
			{
				yield return data;
				yield break;
			}

			using (var ms = new MemoryStream(bs))
			{
				bs = new byte[l];
				for (; ; )
				{
					if (ms.Read(bs, 0, l) != l)
						break;

					yield return bs;
				}
			}//using ms
		}

		private static void FillRowSplit(object item, out SqlBinary result)
		{
			if (item == null)
			{
				result = SqlBinary.Null;
				return;
			}

			if (item is SqlBinary)
			{
				result = (SqlBinary)item;
				return;
			}

			var bs = item as byte[];
			if (bs != null)
			{
				result = bs;
				return;
			}

			var sb = item as SqlBytes;
			if (sb != null)
			{
				if (sb.IsNull)
					result = SqlBinary.Null;
				else
					result = sb.ToSqlBinary();
				return;
			}

			result = SqlBinary.Null;
		}

		/// <summary>
		/// Dictionary
		/// </summary>
		/// <param name="data">data</param>
		/// <returns>IEnumerable</returns>
		[SqlFunction(IsDeterministic = true, IsPrecise = false, FillRowMethodName = "FillRowDictionaryEntry", TableDefinition = "[key] [sql_variant], [value] [sql_variant]")]
		public static IEnumerable Dictionary(SqlBinary data)
		{
			if (data.IsNull)
				yield break;

			var bs = data.Value;
			if (bs == null || bs.Length == 0)
				yield break;

			if (bs.Length <= 16)
			{
				if (Common.InnerItems == null)
					yield break;

				var ht = new Hashtable(Common.InnerItems);
				foreach (var key in ht.Keys)
					yield return new object[] { key, ht[key], };
				yield break;
			}

			var o = new BinaryFormatter().Deserialize(new MemoryStream(data.Value));
			if (o == null)
				yield break;

			var e = o as IDictionary;
			if (e != null)
			{
				foreach (var key in e.Keys)
					yield return new object[] { key, e[key], };
				yield break;
			}

			var v = o;
			var tp = o.GetType();
			var ps = tp.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (var p in ps)
			{
				if (p.GetGetMethod() != null)
				{
					try
					{
						v = p.GetValue(o, null);
					}
					catch
					{
						continue;
					}

					yield return new object[] { p.Name, v, };
				}
			}
			var fs = tp.GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (var f in fs)
			{
				try
				{
					v = f.GetValue(o);
				}
				catch
				{
					continue;
				}

				yield return new object[] { f.Name, v, };
			}
		}

		private static void FillRowDictionaryEntry(object item, out object key, out object value)
		{
			if (item == null)
			{
				key = null;
				value = null;
				return;
			}

			var os = item as object[];
			if (os != null)
			{
				if (os.Length == 0)
				{
					key = null;
					value = null;
					return;
				}

				if (os.Length == 1)
				{
					key = os[0];
					value = null;
					return;
				}

				key = os[0];
				value = os[1];
				return;
			}

			var de = (DictionaryEntry)item;
			key = de.Key;
			value = de.Value;
		}

		/// <summary>
		/// AppendRecord
		/// </summary>
		/// <param name="table">SqlString</param>
		/// <param name="value">SqlBinary</param>
		/// <returns>SqlInt32</returns>
		[SqlProcedure]
		public static SqlInt32 AppendRecord(SqlString table, SqlBinary value)
		{
			if (table.IsNull || string.IsNullOrEmpty(table.Value) ||
				value.IsNull || value.Value == null || value.Value.Length == 0)
				return new SqlInt32(0);

			var bf = new BinaryFormatter();
			var d = bf.Deserialize(new MemoryStream(value.Value)) as IDictionary;
			if (d == null || d.Count == 0)
				return new SqlInt32(0);

			var i = 0;
			var c = string.Empty;
			var v = string.Empty;
			using (var con = Common.OpenConnection(null))
			{
				using (var cmd = con.CreateCommand())
				{
					foreach (var key in d.Keys)
					{
						c = string.Format(",[{0}]", key);
						v = string.Format(",@p__{0}", i);
						cmd.Parameters.Add(new SqlParameter("@p__" + i, d[key]));
						i++;
					}
					cmd.CommandText = string.Format("INSERT INTO {0}({1}) VALUES({2})", table.Value, c.Substring(1), v.Substring(1));
					i = cmd.ExecuteNonQuery();
				}
				Common.CloseConnection(con, null);
			}
			return new SqlInt32(i);
		}

		/// <summary>
		/// UpdateRecord
		/// </summary>
		/// <param name="table">SqlString</param>
		/// <param name="value">SqlBinary</param>
		/// <param name="condition">SqlBinary</param>
		/// <returns>SqlInt32</returns>
		[SqlProcedure]
		public static SqlInt32 UpdateRecord(SqlString table, SqlBinary value, SqlBinary condition)
		{
			if (table.IsNull || string.IsNullOrEmpty(table.Value) ||
				value.IsNull || value.Value == null || value.Value.Length == 0 ||
				condition.IsNull || condition.Value == null || condition.Value.Length == 0)
				return new SqlInt32(0);

			var bf = new BinaryFormatter();
			var d = bf.Deserialize(new MemoryStream(value.Value)) as IDictionary;
			if (d == null || d.Count == 0)
				return new SqlInt32(0);

			var i = 0;
			var t = string.Format("UPDATE {0} SET", table.Value);
			using (var con = Common.OpenConnection(null))
			{
				using (var cmd = new SqlCommand())
				{
					foreach (var key in d.Keys)
					{
						t += string.Format(" [{0}] = @p__{1},", key, i);
						cmd.Parameters.Add(new SqlParameter("@p__" + i, d[key]));
						i++;
					}
					d = bf.Deserialize(new MemoryStream(condition.Value)) as IDictionary;
					if (d == null || d.Count == 0)
						return 0;

					t = t.Remove(t.Length - 1) + " WHERE";
					foreach (var key in d.Keys)
					{
						t += string.Format(" [{0}] = @p__{1}\t", key, i);
						cmd.Parameters.Add(new SqlParameter("@p__" + i, d[key]));
						i++;
					}
					t = t.Remove(t.Length - 1).Replace("\t", " AND ");
					cmd.CommandText = t;
					i = cmd.ExecuteNonQuery();
				}
				Common.CloseConnection(con, null);
			}
			return new SqlInt32(i);
		}

		/// <summary>
		/// UpdateTable
		/// </summary>
		//[SqlProcedure]
		public static void AnyMethod()
		{
			var smds = new SqlMetaData[2];
			smds[0] = new SqlMetaData("CustomerID", SqlDbType.NVarChar, 50);
			smds[1] = new SqlMetaData("CompanyName", SqlDbType.NVarChar, 50);
			var sdr = new SqlDataRecord(smds);
			sdr.SetString(0, "ALFKI");
			sdr.SetString(1, "Alfreds Futterkiste");
			SqlContext.Pipe.Send(sdr);
			SqlContext.Pipe.SendResultsStart(sdr);
			SqlContext.Pipe.SendResultsRow(sdr);
			SqlContext.Pipe.SendResultsEnd();
		}
	}
}
